import QtQuick 1.1
import VPlay 1.0
import Box2D 1.0
import "../particles"

EntityBase {
    entityType: "player"

    // the key-pressed-signals get emitted from the scene when key presses are detected
    // key pressed cant be detected here, because this item has no size
    signal leftPressed(variant event)
    signal rightPressed(variant event)
    signal upPressed(variant event)
    signal downPressed(variant event)

    signal died

    // gets increased over time - it has the same value as the y value of the level
    property int score: 0
    // gets increased when a coin is collected
    property int bonusScore: 0
    // the total score is the one that gets displayed
    property int totalScore: score + (bonusScore * bonusScoreForCoin)
    property int carHealth: 100
    property int fuel: 100
    property int rockets: 10
    // the total count of deaths within this gaming session
    property int deaths: 0

    // this gets added to bonusScore every time the player catches a coin
    property int bonusScoreForCoin: 300

    property alias controller: twoAxisController

    // these are the settings for balancing!
    property real upValue: 550
    property real downValue: 5
    property real rightValue: 250
    property real leftValue: -rightValue

    //    property variant respawnPosition: Qt.point(50,100)

    property bool __isJumping: true
    // cant be initialized with null
    property date lastJumpTime: new Date

    // this is needed internally to find out if the image should be inverted
    property bool __isLookingRight: true

    // this is called when debugging and modifying values at runtime
    onRightValueChanged: console.debug("rightValue changed to", rightValue)

    // set the default pos to the respawnPosition
    //pos: respawnPosition

    // by setting this to true, the removeAllEntities() does not affect this entity, which is called from Level.stopGame()
    preventFromRemovalFromEntityManager: true

    PlayerLogic {
        id: logic
    }
    Image {
        id: sprite
        source: "../img/car_blue-hd.png"
        anchors.centerIn: parent

        // only make the player half the size of a grid
        width: 25
        height: 35
        visible: false // will be visible in default state

    }
    Image {
        id: spriteMovement
        source: "../img/car_blue-hd.png"
        anchors.centerIn: parent
        mirror: __isLookingRight
        width: sprite.width
        height: sprite.height
        visible: false
    }
    Image {
        id: spriteFlying
        source: "../img/car_blue-hd.png"
        anchors.centerIn: parent
        width: 25
        height: 35
        visible: false
    }

    // gets increased when a collision with a block occurs in onBeginContact, and decreased in onEndContact
    // when no blockCollisions happened, the fly-state is active!
    property int blockCollisions: 0

    // a BoxCollider fits better, because then it cant fall down in the edges!
    //    CircleCollider {
    BoxCollider {
        id: collider
        bodyType: Body.Dynamic
        fixedRotation: true

        //force: Qt.point(twoAxisController.yAxis*8000, 0)
        //torque: twoAxisController.xAxis*2000

        //linearVelocity.y: level.levelMovementSpeedMinimum

        //body.bullet: true

        // balancing settings:
        linearDamping: 5.0
        // set friction between 0 and 1
        friction: 0
        // restitution is bounciness - dont bounce, because then the state would be changed too often
        restitution: 0
        // the density normally gets calculated based on the dimensions of the body - it somehow has no effect!
        // if you want to make objects fall faster, increase gravity!
        // with higher density, the player doesnt bounce back from the blocks after jumping, as it is heavier
        //fixture.density: 100

        // this is needed, because otherwise when resetting the level (and the player position), and the body was sleeping before it wouldnt fall down immediately again, because it isnt woken up from sleeping!
        sleepingAllowed: false


        //anchors.centerIn: parent
        anchors.fill: sprite
        //        width: sprite.width-3
        //        height: sprite.height-3

        //        radius: sprite.width/2

        fixture.onBeginContact: {
            var fixture = other;
            var body = other.parent;
            var component = body.parent;
            var collidedEntity = component.owningEntity;
            var collidedEntityType = collidedEntity.entityType;
            if(collidedEntityType === "coin") {
                // the coin is pooled for better performance
                collidedEntity.removeEntity();
                fuel = fuel + 10;
                rockets = rockets + 2;

                // increase the score, and also play a pling sound
                bonusScore++;

                coinSound.play()
            } else if(collidedEntityType === "roost") {
                smokeParticlesEffect.start();
                collidedEntity.collidersActive = false;
                blockCollisions++;
                carHealth = carHealth - 10;
                if (carHealth <= 0)
                {
                    level.stopGame();
                }
            }

        }

        fixture.onEndContact: {
            var fixture = other;
            var body = other.parent;
            var component = body.parent;
            var collidedEntity = component.owningEntity;
            var collidedEntityType = collidedEntity.entityType;
            if(collidedEntityType === "roost") {
                //smokeParticlesEffect.stopLivingParticles();
                //smokeParticlesEffect.stop();
                //collidedEntity.collidersActive = true;
                blockCollisions--;
            }

        }

        // this forwarsd changes from the input controller to the physics system - directly set the linearV for instant response
        // it cant be done like that, because the damping and friction causes the velocity to change!
        //linearVelocity.x: controller.xAxis*rightValue
        //onLinearVelocityChanged: console.debug("linearV.x:", linearVelocity.x, "linearV.y:", linearVelocity.y)
    }

    Sound {
        id: coinSound
        source: "../snd/pling.wav"
    }

    TwoAxisController {
        id: twoAxisController

//        inputActionsToKeyCode : {
//            "fire": Qt.Key_Space
//        }

//        inputs: {
//           "up": Qt.Key_W,
//           "down": Qt.Key_S,
//           "left": Qt.Key_A,
//           "right": Qt.Key_D,
//           "fire": Qt.Key_Space
//       }

        onInputActionPressed: {
            if(actionName === "fire") {
                if (rockets > 0)
                {

                    logic.inputActionPressed(actionName);
                    rockets--;
                }
            }
        }

        onXAxisChanged: {
            console.debug("xAxis changed to", xAxis)
            if(xAxis>0)
                __isLookingRight = true;
            else if(xAxis<0)
                __isLookingRight = false;
        }
    }

    Timer {
        id: updateTimer
        interval: 60
        running: true
        repeat: true
        onTriggered: {
            //            console.debug("controller.xAxis:", controller.xAxis, ", yAxis:", controller.yAxis);

            // this must be done every frame, because the linearVelocity gets reduced because of the damping!
            var xAxis = controller.xAxis;
            if(xAxis) {
                collider.body.linearVelocity.x = xAxis*rightValue;
            }

        }
    }

    SmokeParticles
    {
        id: smokeParticlesEffect
        x: 0
        y: 0
        sourcePositionVariancex: 0
        sourcePositionVariancey: 0
    }


    state: {
        if(blockCollisions==0)
            return "fly";
        else {
            if(controller.xAxis !== 0) {
                return "moveLeftRight";
            }
            return "";
        }
    }

    onXChanged:
    {
        if (x > parent.width - 40)
            x = parent.width - 40 - 1;
        if (x < 90)
            x = 90 + 1;

    }

    onYChanged:
    {
        //console.debug("y: ", y);
        if (y < -parent.height*3)
            stopGame();
    }

    function stopSmoke()
    {
        smokeParticlesEffect.stopLivingParticles();
        smokeParticlesEffect.stop();
    }

    states: [
        State {
            name: ""
            PropertyChanges { target: sprite; visible: true }
        },
        State {
            name: "fly"
            PropertyChanges { target: spriteFlying; visible: true }
        },
        State {
            name: "moveLeftRight"
            PropertyChanges { target: spriteMovement; visible: true }
        }
    ]

}
